
#include "stdafx.h"

/************************************************************************/
/* TaskQueS.h
/* 
/* Sample code for `Multithreading Applications in Win32'
/* 
/* Call ThreadFunc NUM_TASKS times, using no more than THREAD_POOL_SIZE 
/* threads. This version uses WaitForSingleObjects, which gives a very
/* suboptimal solution.
/* 
/* Build command: cl /MD TaskQueS.c
/************************************************************************/

#define WIN32_LEAN_AND_MEAN

#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <conio.h>
#include "MtVerify.h"

DWORD WINAPI ThreadFunc(LPVOID);

#define THREAD_POOL_SIZE 3
#define MAX_THREAD_INDEX THREAD_POOL_SIZE-1
#define NUM_TASKS 6

int main(int argc, char* argv[])
{
	HANDLE hThrd[THREAD_POOL_SIZE];
	int slot = 0;
	DWORD threadId;
	int i;
	DWORD exitCode;

	/*
	* i = 1 2 3 4 5 6 7 8 9 
	* start thread XXXX
	* wait on thread XXXX
	*/
	for (i=1; i<=NUM_TASKS; i++)
	{
		if (i > THREAD_POOL_SIZE)
		{
			WaitForSingleObject(hThrd[slot], INFINITE);
			MTVERIFY(GetExitCodeThread(hThrd[slot], &exitCode));
			printf("Slot %d terminated\n", exitCode);
			MTVERIFY(CloseHandle(hThrd[slot]));
		}

		hThrd[slot] = CreateThread(NULL,
			0,
			ThreadFunc,
			(LPVOID)&slot,
			0,
			&threadId);
		printf("Launched thread #%d (slot %d)\n", i, slot);
		if (++slot > MAX_THREAD_INDEX)
			slot = 0;
	}

	for (slot = 0; slot<THREAD_POOL_SIZE; slot++)
	{
		WaitForSingleObject(hThrd[slot], INFINITE);
		MTVERIFY(CloseHandle(hThrd[slot]));
	}

	printf("All slots terminated\n");

	getch();

	return EXIT_SUCCESS;
}


/*
* This function just calls sleep for a random amount of time, 
* thereby simulating some task that takes time.
*
* the param `n' is the index into the handle array, kept for
* informational purposes
*/
DWORD WINAPI ThreadFunc(LPVOID n)
{
	DWORD* slot = reinterpret_cast<DWORD*>(n);
	srand(GetTickCount());

	Sleep((rand()%8)*500+500);
	printf("Slot %d idle\n", *slot);
	return (*slot);
}